package com.study.springbootsecurity.util;

import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;

import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Base64;

/**
 * @Description: TODO
 * @author: Huangjianyun
 * @date: 2025-06-08 2:37
 */
public class JwtKeyGenerator {
    /**
     * 生成符合 HS256 算法要求的安全密钥 (256 bits)
     * @return Base64 编码的密钥字符串
     */
    public static String generateHS256Key() {
        Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
        return Base64.getEncoder().encodeToString(key.getEncoded());
    }

    /**
     * 生成符合 HS384 算法要求的安全密钥 (384 bits)
     * @return Base64 编码的密钥字符串
     */
    public static String generateHS384Key() {
        Key key = Keys.secretKeyFor(SignatureAlgorithm.HS384);
        return Base64.getEncoder().encodeToString(key.getEncoded());
    }

    /**
     * 生成符合 HS512 算法要求的安全密钥 (512 bits)
     * @return Base64 编码的密钥字符串
     */
    public static String generateHS512Key() {
        Key key = Keys.secretKeyFor(SignatureAlgorithm.HS512);
        return Base64.getEncoder().encodeToString(key.getEncoded());
    }

    /**
     * 从 Base64 编码字符串还原密钥
     * @param base64Key Base64 编码的密钥
     * @return 还原后的 SecretKeySpec 对象
     */
    public static SecretKeySpec getKeyFromBase64(String base64Key, SignatureAlgorithm algorithm) {
        byte[] keyBytes = Base64.getDecoder().decode(base64Key);
        return new SecretKeySpec(keyBytes, algorithm.getJcaName());
    }

    /**
     * 验证密钥长度是否符合算法要求
     * @param base64Key Base64 编码的密钥
     * @param algorithm 签名算法
     * @return 密钥是否安全
     */
    public static boolean isKeySecure(String base64Key, SignatureAlgorithm algorithm) {
        byte[] keyBytes = Base64.getDecoder().decode(base64Key);
        int keyBits = keyBytes.length * 8;

        switch (algorithm) {
            case HS256:
                return keyBits >= 256;
            case HS384:
                return keyBits >= 384;
            case HS512:
                return keyBits >= 512;
            default:
                throw new IllegalArgumentException("Unsupported algorithm: " + algorithm);
        }
    }

    /**
     * 将普通字符串转换为符合 HS256 要求的密钥
     * 注意：此方法仅用于测试或临时用途，生产环境应使用 generateHS256Key()
     * @param secret 原始字符串
     * @return 符合 HS256 要求的密钥
     */
    public static String convertToHS256Key(String secret) {
        // 如果字符串长度不足 32 字节，使用 SHA-256 哈希扩展
        if (secret.getBytes(StandardCharsets.UTF_8).length < 32) {
            try {
                java.security.MessageDigest digest = java.security.MessageDigest.getInstance("SHA-256");
                byte[] hash = digest.digest(secret.getBytes(StandardCharsets.UTF_8));
                return Base64.getEncoder().encodeToString(hash);
            } catch (Exception e) {
                throw new RuntimeException("Failed to hash secret", e);
            }
        }

        // 如果字符串长度超过 32 字节，截取前 32 字节
        byte[] keyBytes = secret.getBytes(StandardCharsets.UTF_8);
        byte[] truncatedKey = new byte[32];
        System.arraycopy(keyBytes, 0, truncatedKey, 0, Math.min(32, keyBytes.length));
        return Base64.getEncoder().encodeToString(truncatedKey);
    }

    // 示例用法
    public static void main(String[] args) {
        // 生成安全密钥 填写application.yml配置文件中
        String hs256Key = generateHS256Key();
        System.out.println("HS256 Key (Base64): " + hs256Key);

        // 验证密钥安全性
        boolean isSecure = isKeySecure(hs256Key, SignatureAlgorithm.HS256);
        System.out.println("密钥是否安全: " + isSecure);

        // 从 Base64 还原密钥
        SecretKeySpec key = getKeyFromBase64(hs256Key, SignatureAlgorithm.HS256);
        System.out.println("还原后的密钥算法: " + key.getAlgorithm());

        // 转换普通字符串为密钥（仅用于测试）
        String convertedKey = convertToHS256Key("MySecretPassphrase123");
        System.out.println("转换后的 HS256 密钥: " + convertedKey);
    }
}
